/*
 * Copyright (C) 2009 M. Hautle.
 * 
 * This file is part of TrackedBean.
 * 
 * TrackedBean is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * TrackedBean is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with TrackedBean. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.trackedbean.business;

import ch.msoftch.internal.*;

/**
 * This is an abstract base class for business components - it provides an indirect access to model properties through a {@link IPropertyResolver}.<br>
 * Use this class for components which may be used on different data structures (i.e. if you need to perform the same logic on a domain object and a
 * corresponding DTO). Use {@link #get(String, Object, Object)} (or a convenience version of it) to retrieve the value of a property.<br>
 * You should use the property names of the domain object as property key if you plan to use the {@link MappingResolver} to reuse the component for mapped
 * beans.<br>
 * 
 * @author M. Hautle
 */
public abstract class AbstractBusinessComponent {
    /** The resolver to use. */
    protected IPropertyResolver resolver;

    /**
     * Returns the current resolver.
     * 
     * @return The resolver.
     */
    public IPropertyResolver getResolver() {
        return resolver;
    }

    /**
     * Sets the resolver to use.
     * 
     * @param resolver The resolver
     */
    public void setResolver(IPropertyResolver resolver) {
        this.resolver = resolver;
    }

    /**
     * Resolves the given property key to the representing property name/EL expression.
     * 
     * @param key The property key
     * @param type The type for which to fetch the information
     * @return The corresponding property/EL expression
     * @throws TechnicalException If something went wrong
     */
    public String getExpression(String key, Class type) throws TechnicalException {
        return resolver.getPath(key, type);
    }

    /**
     * Fetches the value of the given bean denoted by the given property key.
     * 
     * @param <S> The type
     * @param key The property key
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected <S> S get(String key, Object bean, S fallback) {
        return resolver.get(key, bean, fallback);
    }

    /**
     * convenience method for {@link #get(String, Object, Object)}.
     * 
     * @param <S> The type
     * @param key The property key
     * @param type The desired return type
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected <S> S get(String key, Class<S> type, Object bean, S fallback) {
        return resolver.get(key, bean, fallback);
    }

    /**
     * convenience method for {@link #get(String, Object, Object)}.
     * 
     * @param key The property key
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected String getString(String key, Object bean, String fallback) {
        return get(key, bean, fallback);
    }

    /**
     * convenience method for {@link #get(String, Object, Object)}.
     * 
     * @param key The property key
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected Number getNumber(String key, Object bean, Number fallback) {
        return get(key, bean, fallback);
    }

    /**
     * convenience method for {@link #getNumber(String, Object, Number)}.
     * 
     * @param key The property key
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected byte getByte(String key, Object bean, byte fallback) {
        final Number res = getNumber(key, bean, null);
        return res != null ? res.byteValue() : fallback;
    }

    /**
     * convenience method for {@link #getNumber(String, Object, Number)}.
     * 
     * @param key The property key
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected short getShort(String key, Object bean, short fallback) {
        final Number res = getNumber(key, bean, null);
        return res != null ? res.shortValue() : fallback;
    }

    /**
     * convenience method for {@link #getNumber(String, Object, Number)}.
     * 
     * @param key The property key
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected int getInt(String key, Object bean, int fallback) {
        final Number res = getNumber(key, bean, null);
        return res != null ? res.intValue() : fallback;
    }

    /**
     * convenience method for {@link #getNumber(String, Object, Number)}.
     * 
     * @param key The property key
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected long getLong(String key, Object bean, long fallback) {
        final Number res = getNumber(key, bean, null);
        return res != null ? res.longValue() : fallback;
    }

    /**
     * convenience method for {@link #getNumber(String, Object, Number)}.
     * 
     * @param key The property key
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected float getFloat(String key, Object bean, float fallback) {
        final Number res = getNumber(key, bean, null);
        return res != null ? res.floatValue() : fallback;
    }

    /**
     * convenience method for {@link #getNumber(String, Object, Number)}.
     * 
     * @param key The property key
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected double getDouble(String key, Object bean, double fallback) {
        final Number res = getNumber(key, bean, null);
        return res != null ? res.doubleValue() : fallback;
    }

    /**
     * Convenience method for {@link #get(String, Object, Object)}.
     * 
     * @param key The property key
     * @param bean The bean from which to fetch the value
     * @param fallback The fallback value
     * @return The fetched value or the fallback
     */
    protected char getChar(String key, Object bean, char fallback) {
        final Character c = get(key, bean, null);
        return c != null ? c.charValue() : fallback;
    }
}
